/*
 * serialize.cpp
 *
 *  Created on: 2012-9-26
 *      Author: Administrator
 */

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <libxml/parser.h>

#include "cppSerialize.hpp"

static void publicListLength( const char* name , char *to ) {
	sprintf( to , "%sLength" , name ) ;
}
static void privateListLength( const char* name , char *to ) {
	sprintf( to , "private%c%sLength" , toupper( name[0] ) , name + 1 ) ;
}
static void privateListName( const char* name , char *to ) {
	sprintf( to , "private%c%s" , toupper( name[0] ) , name + 1 ) ;
}

static size_t makeHeaderMember( char* write_to , const char* type , const char* name , const char* comment ) {
	if( comment == NULL ) {
		return sprintf( write_to , "	public: %s %s ;\n"
				, type , name ) ;
	} else {
		return sprintf( write_to , "	public: %s %s ;\t\t//%s\n"
				, type , name , comment ) ;
	}
}
static size_t makeHeaderListMember( char* write_to , const char* type , const char* name , const char* comment ) {
	char strPrivateListLength[256] ;
	char strPublicListLength[256] ;
	char listName[256] ;
	char* pWrite = write_to ;

	publicListLength ( name , strPublicListLength ) ;
	privateListLength( name , strPrivateListLength ) ;
	privateListName( name , listName ) ;
	/* 申明 */
	pWrite += sprintf( pWrite , "	public: uint32_t %s ;\n"
			"	private: uint32_t %s ;\n"
			"	private: %s *%s ;"
			, strPublicListLength , strPrivateListLength , type , listName ) ;
	/* 注释 */
	if( comment == NULL ) {
		pWrite += sprintf( pWrite , "\n" ) ;
	} else {
		pWrite += sprintf( pWrite , "t\t//%s\n" , comment ) ;
	}
	/* 导出函数 */
	pWrite += sprintf( pWrite , "	public: uint32_t %sMaxLength() ;\n"
			"	public: %s* %s() ;\n"
			"	public: void malloc%s( uint32_t length ) ;\n" ,
			name , type , name , name ) ;
	return pWrite - write_to ;
}
/**
 * 头文件
 */
size_t makeHeader( char* write_to , xmlNode* node  , enum SERIALIZE_TYPE type ) {
	char *pWrite = write_to ;
	xmlNode* memberNode ;
	char *nodeName = xmlGetProp( node , "name" ) ;

	pWrite += sprintf( pWrite , "class %s { \n" , nodeName ) ;
	pWrite += sprintf( pWrite , "public :\n" ) ;

	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		const char* type = xmlGetProp( memberNode , "type" ) ;
		const char* name = xmlGetProp( memberNode , "name" ) ;
		const char* comment = xmlGetProp( memberNode , "comment" ) ;
		if( xmlStrcmp( memberNode->name , "member" ) == 0 ) {
			pWrite += makeHeaderMember( pWrite , type , name , comment ) ;
		} else if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			pWrite += makeHeaderListMember( pWrite , type , name , comment ) ;
		} else {
			printf( "错误的成员类型：[%s]\n" , memberNode->name ) ;
			return 1 ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	pWrite += sprintf( pWrite , "private :\n" ) ;
	pWrite += sprintf( pWrite , "	static const uint16_t messageId ;\n" ) ;
//	pWrite += sprintf( pWrite , "	CMsgTyped *msgTyped ;\n" ) ;
	pWrite += sprintf( pWrite , "public :\n" ) ;
	pWrite += sprintf( pWrite , "	%s() ;\n" , nodeName ) ;
	pWrite += sprintf( pWrite , "	~%s() ;\n" , nodeName ) ;
	if( type == SERIALIZE_TYPE_TYPE		// 生成序列化方法
			|| type == SERIALIZE_TYPE_RESPOND ) {
		pWrite += sprintf( pWrite , "	CMsgTyped* Serialize( CMsgTyped *msgTyped ) ;\n" ) ;
	}
	if( type == SERIALIZE_TYPE_TYPE		// 生成反序列化方法
			|| type == SERIALIZE_TYPE_REQUEST ) {
		pWrite += sprintf( pWrite , "	CMsgTyped* Unserialize( CMsgTyped *msgTyped ) ;\n" ) ;
	}
	pWrite += sprintf( pWrite , "} ;\n\n" ) ;

	return pWrite - write_to ;
}

/**
 * 构造函数
 */
size_t makeConstructor( char* write_to , xmlNode* node ) {
	char *pWrite = write_to ;
	xmlNode* memberNode ;
	char *nodeName = xmlGetProp( node , "name" ) ;

	pWrite += sprintf( pWrite , "%s::%s() {\n" , nodeName ,nodeName ) ;
	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		char* type = xmlGetProp( memberNode , "type" ) ;
		char* name = xmlGetProp( memberNode , "name" ) ;
		if( xmlStrcmp( memberNode->name , "member" ) == 0 ) {
			if(
//					strcmp( type , "uint8_t" ) == 0
//					|| strcmp( type , "uint16_t" ) == 0
					strcmp( type , "uint32_t" ) == 0
//					|| strcmp( type , "uint64_t" ) == 0
//					|| strcmp( type , "int8_t" ) == 0
//					|| strcmp( type , "int16_t" ) == 0
					|| strcmp( type , "int32_t" ) == 0
//					|| strcmp( type , "int64_t" ) == 0
			) {
				pWrite += sprintf( pWrite , "	%s = 0 ;\n" ,  name ) ;
			} else if( strcmp( type , "float" ) == 0 ) {
				pWrite += sprintf( pWrite , "	%s = 0.0f ;\n" ,  name ) ;
			} else if( strcmp( type , "string" ) == 0 ) {
				pWrite += sprintf( pWrite , "	%s = \"\" ;\n" ,  name) ;
			} else {	// 自定义类型，不显示初始化
				 ;
			}
		}
		else if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			char strPublicListLength[256] ;
			char strPrivateListLength[256] ;
			char listName[256] ;
			publicListLength( name , strPublicListLength ) ;
			privateListLength( name, strPrivateListLength ) ;
			privateListName( name , listName ) ;
			pWrite += sprintf( pWrite , "	%s = 0 ;\n" ,  strPublicListLength ) ;
			pWrite += sprintf( pWrite , "	%s = 0 ;\n" ,  strPrivateListLength ) ;
			pWrite += sprintf( pWrite , "	%s = NULL ;\n" ,  listName ) ;
		}
		else {
			printf( "错误的成员类型：[%s]\n" , memberNode->name ) ;
			return 1 ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	pWrite += sprintf( pWrite ,
//			"	msgTyped = NULL ;\n"
			"} ;\n\n" ) ;
	/* 为数组(list)生成 get/set 方法 */
	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			char* type = xmlGetProp( memberNode , "type" ) ;
			char* name = xmlGetProp( memberNode , "name" ) ;
			char strPublicListLength[256] ;
			char strPrivateListLength[256] ;
			char listName[256] ;
			publicListLength( name , strPublicListLength ) ;
			privateListLength( name , strPrivateListLength ) ;
			privateListName( name , listName ) ;

			pWrite += sprintf( pWrite ,
					"uint32_t %s::%sMaxLength() { return this->%s ; }\n"
					"%s* %s::%s() { return this->%s ; }\n"
					"void %s::malloc%c%s( uint32_t length ) { \n"
					"	if( this->%s ) delete[] this->%s ;\n"
					"	this->%s = length ;\n"
					"	this->%s = length ;\n"
					"	this->%s = new %s[length] ;\n"
					"}\n\n" ,
					nodeName , name , strPrivateListLength ,
					type , nodeName , name , listName ,
					nodeName , name[0] , name+1 ,
					listName , listName ,
					strPublicListLength , strPrivateListLength ,
					listName , type ) ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	return pWrite - write_to ;
}
/**
 *  析构函数
 */

size_t makeDestruction( char* write_to , xmlNode* node ) {
	char *pWrite = write_to ;
	xmlNode* memberNode ;
	char *nodeName = xmlGetProp( node , "name" ) ;

	pWrite += sprintf( pWrite , "%s::~%s() {\n" , nodeName ,nodeName ) ;
	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		char* name =  xmlGetProp( memberNode , "name" ) ;
		char listName[256] ;
		privateListName( name , listName ) ;
		/* 回收列表内存 */
		if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			pWrite += sprintf( pWrite , "	if( %s ) delete[] %s ;\n" , listName , listName ) ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	pWrite += sprintf( pWrite ,
//			"if( msgTyped ) delete msgTyped ;\n"
			"} ;\n\n" ) ;

	return pWrite - write_to ;
}

/*
 * 序列化一个字段
 */
static size_t makeTypeSerialize( char* write_to , char* name ,char* type ) {
	char *pWrite = write_to ;
	if(	strcmp( type , "uint32_t" ) == 0
			|| strcmp( type , "int32_t" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	msgTyped->SetInt( %s ) ;\n" ,
				name ) ;
	} else if( strcmp( type , "float" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	msgTyped->SetFloat( %s ) ;\n" ,
				name ) ;
	} else if( strcmp( type , "string" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	msgTyped->SetString( %s.c_str( ) ) ;\n" ,
				name ) ;
	} else {	// 自定义的数据类型
		pWrite += sprintf( pWrite ,
				"	%s.Serialize( msgTyped ) ;\n" ,
				name ) ;
	}
	return pWrite - write_to ;
}


/**
 * 序列化
 */
size_t makeSerialize( char* write_to , xmlNode* node , enum SERIALIZE_TYPE serializeType ) {
	char *pWrite = write_to ;
	xmlNode* memberNode ;
	char *nodeName = xmlGetProp( node , "name" ) ;

	pWrite += sprintf( pWrite , "CMsgTyped* %s::Serialize( CMsgTyped * msgTyped ) {\n" ,
			nodeName ) ;
//	/* 不加入模块号和消息号 */
//	if( serializeType == SERIALIZE_TYPE_RESPOND ) {
//		// 应答的包加入模块号和消息号
//		pWrite += sprintf( pWrite ,
//				"	msgTyped->SetInt( thisModuleID ) ;\n" ) ;
//		pWrite += sprintf( pWrite ,
//				"	msgTyped->SetInt( messageId ) ;\n" ) ;
//	}
	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		char* type = xmlGetProp( memberNode , "type" ) ;
		char* name = xmlGetProp( memberNode , "name" ) ;
		if( xmlStrcmp( memberNode->name , "member" ) == 0 ) {
			pWrite += makeTypeSerialize( pWrite , name , type ) ;
		}
		else if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			char strPublicListLength[100] ;
			char strPrivateListLength[100] ;
			char listName[256] ;
			char nameList[256] ;
			publicListLength( name , strPublicListLength ) ;
			privateListLength( name , strPrivateListLength ) ;
			privateListName( name , listName ) ;

			/** 列表的序列化 **/
			pWrite += sprintf( pWrite ,
					"	{\n"
					"		size_t realLength ; \n"
					"		if( %s > %s ) {\n"
					"			printf( \"ERROR --> [%%s:%%d] 越界访问[%%s]\\n\" , __FILE__ , __LINE__ , \"%s\" ) ;\n"
					"			realLength = %s ;\n"
					"		} else {\n"
					"			realLength = %s ;\n"
					"		}\n" ,
					strPublicListLength , strPrivateListLength ,
					listName ,
					strPrivateListLength , strPublicListLength ) ;
			pWrite += sprintf( pWrite ,
					"		msgTyped->SetInt( realLength ) ;\n"
					"		for( size_t i = 0 ; i < realLength ; ++i ) {\n"  ) ;
			sprintf( nameList , "%s[i]" , listName ) ;
			pWrite += makeTypeSerialize( pWrite , nameList , type ) ;
			pWrite += sprintf( pWrite , "		}\n" ) ;
			pWrite += sprintf( pWrite , "	}\n" ) ;
			/** end of 列表的序列化 **/
		}
		else {
			printf( "错误的成员类型：[%s]\n" , memberNode->name ) ;
			return 1 ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	pWrite += sprintf( pWrite , "	return msgTyped ;\n" ) ;
	pWrite += sprintf( pWrite , "} ;\n\n" ) ;

	return pWrite - write_to ;
}



/*
 * 反序列化一个字段
 */
static size_t makeTypeUnserialize( char* write_to , char* name ,char* type ) {
	char *pWrite = write_to ;
	if( strcmp( type , "uint32_t" ) == 0
			|| strcmp( type , "int32_t" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	%s = msgTyped->IntVal() ;\n" ,
				name ) ;
	} else if(  strcmp( type , "float" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	%s = msgTyped->FloatVal() ;\n" ,
				name ) ;
	} else if( strcmp( type , "string" ) == 0 ) {
		pWrite += sprintf( pWrite ,
				"	%s = msgTyped->StringVal() ;\n" ,
				name ) ;
	} else {	// 自定义的数据类型
		pWrite += sprintf( pWrite ,
				"	%s.Unserialize( msgTyped ) ;\n" ,
				name ) ;
	}
	return pWrite - write_to ;
}
/*
 * 反序列化
 */
size_t makeUnserialize( char* write_to , xmlNode *node ) {
	char *pWrite = write_to ;
	xmlNode* memberNode ;
	char *nodeName = xmlGetProp( node , "name" ) ;

	pWrite += sprintf( pWrite , "CMsgTyped* %s::Unserialize( CMsgTyped* msgTyped ) {\n" ,
			nodeName ) ;
	memberNode = xmlFirstElementChild( node ) ;
	while( memberNode ) {
		char* type = xmlGetProp( memberNode , "type" ) ;
		char* name = xmlGetProp( memberNode , "name" ) ;
		if( xmlStrcmp( memberNode->name , "member" ) == 0 ) {
			pWrite += makeTypeUnserialize( pWrite , name , type ) ;
		}
		else if( xmlStrcmp( memberNode->name , "list" ) == 0 ) {
			char strPublicListLength[256] ;
			char strPriateListLength[256] ;
			char listName[256] ;
			char nameList[256] ;
			publicListLength( name , strPublicListLength ) ;
			privateListLength( name , strPriateListLength ) ;
			privateListName( name , listName ) ;
			pWrite += sprintf( pWrite , "	%s = msgTyped->IntVal( ) ;\n" , strPriateListLength ) ;
			pWrite += sprintf( pWrite , "	%s = %s ;\n" , strPublicListLength , strPriateListLength ) ;
			pWrite += sprintf( pWrite ,
					"	%s = new %s[%s] ;\n" ,
					listName , type , strPriateListLength ) ;
			pWrite += sprintf( pWrite , "	for( size_t i = 0 ; i < %s ; ++i ) {\n" ,	strPriateListLength ) ;
			sprintf( nameList , "%s[i]" , listName ) ;
			pWrite += makeTypeUnserialize( pWrite , nameList , type ) ;
			pWrite += sprintf( pWrite , "	}\n" ) ;
		}
		else {
			printf( "错误的成员类型：[%s]\n" , memberNode->name ) ;
			return 1 ;
		}
		memberNode = xmlNextElementSibling( memberNode ) ;
	}
	pWrite += sprintf( pWrite , "	return msgTyped ;\n" ) ;
	pWrite += sprintf( pWrite , "} ;\n\n" ) ;

	return pWrite - write_to ;
}
























